﻿using Protocol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using ServerFrame;
using Protocol.DTO;
using Gameserver.Cache;
using System.Threading;

namespace Gameserver.Logic.Match
{
    public class MatchHandler :AbsOnceHandler, IMessageHandler
    {
        RoleCache roleCache;
        UserCache userCache;
        public int room_id = 1;//缓存中的房间ID

        public MatchHandler()
        {
            Logic_Type = GameProtocol.match;
            roleCache = CacheFactory.roleCache;
            userCache = CacheFactory.userCache;
        }
        public ConcurrentDictionary<int, MatchRoom> MatchRoomDic = new ConcurrentDictionary<int, MatchRoom>();
        public ConcurrentDictionary<Mytoken, int> RoomDic_token = new ConcurrentDictionary<Mytoken, int>();
        public ConcurrentStack<MatchRoom> RoomPool = new ConcurrentStack<MatchRoom>();
        public void OnClientConnected(Mytoken token)
        {

        }

        public void OnClientClose(Mytoken token, string error)
        {
            ExitReq(token);
        }

        public void OnMessageRecive(Mytoken token, ServerFrame.TransModel model)
        {
            switch (model.command)
            {
                case MatchProtocol.Refresh_CREQ:
                    if(MatchRoomDic.Count==0)
                    {
                        this.Send(token, -1, MatchProtocol.Refresh_SRES);
                    }
                    RefreshReq(token);
                    break;
                case MatchProtocol.Create_CREQ:
                    int result = CreateReq(token);
                    if(result!=0)
                    {
                        Send(token, result, MatchProtocol.Create_SRES);
                    }
                    else
                    {
                        Send(token, result, MatchProtocol.Create_SRES,GetRoom_DTO(token));
                    }
                    break;
                case MatchProtocol.Exit_CREQ:
                    ExitReq(token);
                    break;
                case MatchProtocol.Enter_CREQ:
                    EnterReq(token);
                    break;
                case MatchProtocol.Change_CREQ:
                    ChangeReq(token);
                    break;
                case MatchProtocol.Chat_CREQ:
                    ChatReq(token, model);
                    break;
                default:
                    break;
            }
        }
        void RefreshReq(Mytoken token)
        {
            List<MatchRoom> rooms = MatchRoomDic.Values.ToList<MatchRoom>();
            Room_DTO[] dtos = new Room_DTO[rooms.Count];
            for(int i=0;i<dtos.Length;i++)
            {
                dtos[i] = new Room_DTO(rooms[i].id,rooms[i].master_name);
                dtos[i].MaxNum = rooms[i].MaxNum * 2;
                dtos[i].num = rooms[i].teamone.Count + rooms[i].teamtwo.Count;
                dtos[i].teamone = null;
                dtos[i].teamtwo = null;
            }
            this.Send(token, MatchProtocol.Refresh_SRES, dtos);
        }
        /// <summary>
        /// 创建房间
        /// </summary>
        /// <param name="token"></param>
        /// <param name="model"></param>
        /// <returns>
        /// 0 创建房间成功
        /// 1 该连接已在房间之中
        /// 2 该连接没有登陆角色
        /// </returns>
        int CreateReq(Mytoken token)
        {
            if(RoomDic_token.ContainsKey(token))
            {
                return 1;
            }
            string rname = roleCache.GetNameByToken(token);
            if(rname==null)
            {
                return 2;
            }
            MatchRoom room;
            if(RoomPool.Count>0)
            {
                if(!RoomPool.TryPop(out room))
                {
                    room = new MatchRoom(Interlocked.Increment(ref room_id), rname,this);
                }
            }
            else
            {
                room = new MatchRoom(Interlocked.Increment(ref room_id), rname,this);
            }
            room.master_name = rname;
            room.teamone.Add(token);
            room.teamonename.Add(rname);
            MatchRoomDic.TryAdd(room.id, room);
            RoomDic_token.TryAdd(token, room.id);
            return 0;
        }
        void ExitReq(Mytoken token)
        {
            //先检查RoomDic_token中是否存在该token
            if(!RoomDic_token.ContainsKey(token))
            {
                return;
            }
            MatchRoom room = MatchRoomDic[RoomDic_token[token]];
            room.Exit(token, roleCache.GetNameByToken(token));
            if(room.teamone.Count+room.teamtwo.Count==0)
            {
                room.Clear();
                MatchRoomDic.TryRemove(room.id, out room);
                RoomPool.Push(room);
            }
        }
        void EnterReq(Mytoken token)
        {
            if(RoomDic_token.ContainsKey(token))
            {
                //1 代表该连接已有房间
                Send(token, 1, MatchProtocol.Enter_BRO);
                return;
            }
            MatchRoom room=MatchRoomDic[RoomDic_token[token]];
            if(room.teamone.Count+room.teamtwo.Count>=room.MaxNum*2)
            {
                //2 代表房间已满
                Send(token, 2, MatchProtocol.Enter_BRO);
                return;
            }
            room.Enter(token, roleCache.GetNameByToken(token));
        }
        void ChangeReq(Mytoken token)
        {
            if(!RoomDic_token.ContainsKey(token))
            {
                //1 代表该连接不在房间内
                Send(token, 1, MatchProtocol.Change_BRO);
                return;
            }
            MatchRoom room = MatchRoomDic[RoomDic_token[token]];
            room.Change(token, roleCache.GetNameByToken(token));

        }
        void ChatReq(Mytoken token,TransModel model)
        {
            if (!RoomDic_token.ContainsKey(token))
            {
                //1 代表该连接不在房间内
                Send(token, 1, MatchProtocol.Chat_BRO);
                return;
            }
            MatchRoom room = MatchRoomDic[RoomDic_token[token]];
            room.Chat(roleCache.GetNameByToken(token),model);
        }
        Room_DTO GetRoom_DTO(Mytoken token)
        {
            MatchRoom room = MatchRoomDic[RoomDic_token[token]];
            Room_DTO dto = new Room_DTO(room.id, room.master_name);
            dto.MaxNum = room.MaxNum * 2;
            dto.num = room.teamone.Count + room.teamtwo.Count;
            dto.teamone = room.teamonename.ToArray<string>();
            dto.teamtwo = room.teamonename.ToArray<string>();
            return dto;
        }

    }
}
